#include "stdafx.h"
#include "textstream.h"
#include "StringToolkit.h"
#include <atlenc.h>

static const int TEXTSTREAM_BUFFERSIZE = 16384;

CTextStream::CTextStream(CStdioFile *device)
	: _device(device) 
{
	_internalFile = NULL;
#ifdef _UNICODE
	_device->Write("\xEF\xBB\xBF", 3);
#endif
}

CTextStream::CTextStream(FILE *internalFile)
	: _internalFile(internalFile)
{
	_device = new CStdioFile(_internalFile);
}

CTextStream::~CTextStream() 
{
	flushWriteBuffer();

	if (_internalFile)
		delete _device;
	else
		_device->Close();
}

CTextStream & CTextStream::operator<<(TCHAR ch)
{
	write(ch);
	return *this;
}

CTextStream & CTextStream::operator<<(signed short i)
{
	CString str = CStringToolkit::IntToStr(i);
	write(str);
	return *this;
}

CTextStream & CTextStream::operator<<(unsigned short i)
{
	CString str = CStringToolkit::IntToStr(i);
	write(str);
	return *this;
}

CTextStream	& CTextStream::operator<<(signed int i)
{
	CString str = CStringToolkit::IntToStr(i);
	write(str);
	return *this;
}

CTextStream & CTextStream::operator<<(unsigned int i)
{
	CString str = CStringToolkit::IntToStr(i);
	write(str);
	return *this;
}

CTextStream & CTextStream::operator<<(signed long i)
{
	CString str = CStringToolkit::IntToStr(i);
	write(str);
	return *this;
}

CTextStream & CTextStream::operator<<(unsigned long i)
{
	CString str = CStringToolkit::IntToStr(i);
	write(str);
	return *this;
}

CTextStream & CTextStream::operator<<(float f)
{
	*this << (double)f;
	return *this;
}

CTextStream & CTextStream::operator<<(double f)
{
	CString str = CStringToolkit::DblToStr(f);
	write(str);
	return *this;
}

CTextStream & CTextStream::operator<<(const CString &s)
{
	write(s);
	return *this;
}

CTextStream & CTextStream::operator<<(const TCHAR *c)
{
	CString str = c;
	write(str);
	return *this;
}

void CTextStream::flushWriteBuffer()
{
	if (_device == NULL)
		return;

	if (_writeBuffer.IsEmpty())
		return;

	if (_internalFile == NULL)
	{
#ifdef _UNICODE
		int nSrcLen = _writeBuffer.GetLength();


		CStringA utf8String(_writeBuffer);
		int nBufLen = ::WideCharToMultiByte(CP_UTF8, NULL, _writeBuffer, _writeBuffer.GetLength(), NULL, 0, NULL, NULL);
		LPSTR buffer = utf8String.GetBufferSetLength(nBufLen);

		int nLen = AtlUnicodeToUTF8(_writeBuffer, nSrcLen, buffer, nBufLen);
		buffer[nLen] = 0;
		utf8String.ReleaseBuffer();

		_device->Write(buffer, nLen);
#else
		_device->WriteString(_writeBuffer);
#endif
	}
	else
		_device->WriteString(_writeBuffer);
	
	_device->Flush();
	_writeBuffer.Empty();
}

void CTextStream::write(const TCHAR *data, int len)
{
	_writeBuffer.Append(data, len);

	if (_writeBuffer.GetLength() > TEXTSTREAM_BUFFERSIZE)
		flushWriteBuffer();
}

void CTextStream::write(TCHAR ch)
{
	_writeBuffer += ch;

	if (_writeBuffer.GetLength() > TEXTSTREAM_BUFFERSIZE)
		flushWriteBuffer();
}

void CTextStream::write(const CString& str)
{
	write((const TCHAR*)str, str.GetLength());
}

